package user;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import validator.UserValidator;
import exceptions.InvalidUserNameException;
import exceptions.NotFriendException;
import exceptions.UserNotFoundException;

/**
 * Implements a controller to users
 * @author Alexandre, Cristovao, Raul, Rodolpho, Tales
 * @version 1.1
 * @milestone Number 2
 */
public class UserControl {

	private Map<String, Loggable> users;
	private Map<String, Loggable> loggedUsers;

	private static UserControl controller = null;

	protected UserControl() {
		this.users = new HashMap<String, Loggable>();
		this.loggedUsers = new HashMap<String, Loggable>();

	}

	/**
	 * Get the single instance of the user controller
	 * @return
	 */
	public synchronized static UserControl getInstance() {
		if (controller == null) {
			controller = new UserControl();
		}
		return controller;
	}

	/**
	 * Get all users registered in database
	 * 
	 * @return users
	 */
	public Map<String, Loggable> getUsers() {
		return this.users;
	}

	/**
	 * Set current database users on active system.
	 * 
	 * @param users
	 *            loaded data from database
	 */
	public void setUsers(Map<String, Loggable> users) {
		this.users = users;
	}

	/**
	 * Get list of current logged users
	 * 
	 * @return logged Users
	 */
	public Map<String, Loggable> getLoggedUsers() {
		return this.loggedUsers;
	}

	/**
	 * Set a list of logged users
	 * 
	 * @param loggedUsers
	 */
	public void setLoggedUsers(Map<String, Loggable> loggedUsers) {
		this.loggedUsers = loggedUsers;
	}

	/**
	 * Inserts a user on a userslist of the system.
	 * 
	 * @param user
	 */
	public void insertUser(Loggable user) {
		this.users.put(user.getUserName(), user);
	}

	/**
	 * Remove user by username.
	 * 
	 * @param userName
	 *            - user who will be removed from friendlist.
	 * @throws InvalidUserNameException
	 *             - if the userName is invalid
	 * @throws UserNotFoundException
	 *             - if user wasn't found
	 */
	public void removeUserByUserName(String userName)
			throws InvalidUserNameException, UserNotFoundException {
		// verify if the user exists
		UserValidator.validateUserName(userName);
		Loggable user = users.get(userName);
		if (user == null)
			throw new UserNotFoundException("O usuario nao existe.");
		List<Loggable> friends = user.getFriendsList();

		// remove the user from his friends's lists
		for (int i = 0; i < friends.size(); i++) {
			try {
				user.removeFriend(friends.get(i));
			} catch (NotFriendException e) {
				throw new UserNotFoundException(
						"Erro ao remover usuario da lista dos seus amigos");
			}

		}
		this.users.remove(userName);
	}

	/**
	 * Gets a user by username
	 * 
	 * @param userName
	 *            - user requested
	 * @return user
	 * @throws UserNotFoundException 
	 * @throws InvalidUserNameException 
	 * @throws UserNotFoundException 
	 * @throws UserNotFoundException 
	 * @throws InvalidUserNameException
	 *             - if username is invalid or user wasn't found
	 * @throws UserNotFoundException 
	 * @throws InvalidUserNameException 
	 */
	public Loggable getUserByUserName(String userName) throws UserNotFoundException 
			{
		Loggable user = this.users.get(userName);
		if (user == null)throw new UserNotFoundException("O usuario nao existe.");
		return user;
	}

	/**
	 * Gets a logged user by username
	 * 
	 * @param userName
	 *            - user who will searched
	 * @return user searched
	 * @throws InvalidUserNameException
	 *             - if username is invalid or wasn't found.
	 */
	public Loggable getLoggedUserByUserName(String userName)
			throws InvalidUserNameException {
		UserValidator.validateUserName(userName);
		return this.loggedUsers.get(userName);
	}

	/**
	 * Insert a user in logged list users
	 * 
	 * @param user
	 *            - the user who will be logged
	 */
	public void insertLoggedUser(Loggable user) {
		this.loggedUsers.put(user.getUserName(), user);
	}

	/**
	 * Remove a user from logged
	 * 
	 * @param userName
	 * @throws InvalidUserNameException
	 */
	public void removeLoggedUserByUserName(String userName)
			throws InvalidUserNameException {
		UserValidator.validateUserName(userName);
		
		this.loggedUsers.remove(userName);
	}

	/**
	 * Clean the system. Delete all users and logged users
	 */
	public void clear() {
		this.users.clear();
		this.loggedUsers.clear();
	}
}